import sys
from PyQt4.QtGui import *
from S3D.SoundsDeployer.UI.SelectBuildDlg import Ui_SelectBuildDlg
from S3D import QtHelper, XboxShell
from multiprocessing import Lock
from S3D.Decorators import thread
import os

def _removeAllChilds(item):
    while item.childCount() > 0:
        item.removeChild(item.child(0))

class RefreshData:
    def __init__(self, item):
        self.lock = Lock()
        self.isFinished = False
        self.buildList  = None
        self.item = item

@thread
def refreshTask(xbox, data, config):
    try:
        def _search(path, exe, deep):
            # search for .xex
            res = XboxShell.listDir(os.path.join(path, exe), xbox)

            # test .xex
            for candidate in res or []:
                _, ext = os.path.splitext(candidate)
                if ext.lower() == '.xex':
                    return path

            # check subfolders
            if not deep:
                return None

            subPath = XboxShell.listDir(os.path.join(path, "*.*"), xbox)
            if not subPath:
                return None

            for name in subPath:
                res = _search(os.path.join(path, name), exe, deep - 1)
                if res is not None:
                    return res

            return None

        candidates = XboxShell.listDir("xE:\\*.*", xbox)
        if candidates is None:
            return

        res = []
        for name in candidates:
            path = _search("xE:\\%s" % name, "%s*.xex" % config.workspace, 1)
            if path:
                res.append((name, path))

        with data.lock:
            data.buildList = res
    finally:
        with data.lock:
            data.isFinished = True

class SelectBuildDlg(QDialog):
    def __init__(self, config, parent = None):
        super(SelectBuildDlg, self).__init__(parent)

        self.ui = Ui_SelectBuildDlg()
        self.ui.setupUi(self)

        self.cfg = config

        self.initXboxList()

        self.isRefreshing = False
        self.onRefresh()

    def initXboxList(self):
        for p in self.cfg.xboxList:
            item = QTreeWidgetItem([p])
            self.ui.buildsTree.addTopLevelItem(item)

    def onAdd(self):
        name = QtHelper.getValue(self, self.tr("Enter Xbox360 name"), self.tr("Name:"))
        if name in self.cfg.xboxList:
            QMessageBox.warning(self, self.tr("Warning"), self.tr("Xbox360 with such name already exists"), QMessageBox.Ok)
            return

        self.cfg.xboxList.append(name)

        item = QTreeWidgetItem([name])
        self.ui.buildsTree.addTopLevelItem(item)
        self.refreshItem(item)
        self.ui.buildsTree.update()

    def onRemove(self):
        item = self.ui.buildsTree.currentItem()
        if not item:
            return

        name = item.text(0)

        res = QMessageBox.warning(self, self.tr("Remove Xbox360"), self.tr("Are you sure you want to remove this Xbox360?"), QMessageBox.Yes | QMessageBox.No)
        if res != QMessageBox.Yes:
            return

        self.cfg.xboxList.remove(name)
        self.ui.buildsTree.removeItemWidget(item, 0)
        self.ui.buildsTree.update()

    def refreshItem(self, item):
        name = item.text(0)

        # create task
        data = RefreshData(item)
        refreshTask(name, data, self.cfg)
        self.refreshData.append(data)

        # set temporary text
        _removeAllChilds(item)

        item.addChild(QTreeWidgetItem([UPDATE_LABEL]))
        item.setExpanded(True)

    def onRefresh(self):
        self.refreshData = []

        count = self.ui.buildsTree.topLevelItemCount()
        for k in range(count):
            item = self.ui.buildsTree.topLevelItem(k)
            self.refreshItem(item)

        if not self.isRefreshing:
            self.startTimer(100)
            self.isRefreshing = True

    def onAccept(self):
        item = self.ui.buildsTree.currentItem()
        if not item or not hasattr(item, "path"):
            return

        self.selectedXBox  = item.parent().text(0)
        self.selectedBuild = item.text(0)
        self.selectedPath  = item.path

        self.accept()

    def timerEvent(self, e):
        if not self.refreshData:
            return

        finished = True

        for index in range(len(self.refreshData)):
            task = self.refreshData[index]

            if not task:
                continue
                
            with task.lock:
                if not task.isFinished:
                    finished = False
                    continue

                self.refreshData[index] = None

                item      = task.item
                buildList = task.buildList

            _removeAllChilds(item)

            if buildList is None:
                item.addChild(QTreeWidgetItem([ERROR_LABEL]))
                continue

            for name, path in sorted(buildList):
                child = QTreeWidgetItem([name])
                child.path = path
                item.addChild(child)

            self.ui.buildsTree.update()

        if finished:
            self.refreshData = []

if __name__ == '__main__':
    from S3D.SoundsDeployer import Config

    qApp = QtHelper.qApp

    cfg = Config.load()
    dlg = SelectBuildDlg(cfg)

    res = dlg.exec_()
    if res == QDialog.Accepted:
        cfg.save()

    sys.exit()